﻿#include "systick.h"
#include "stm32f10x.h"

volatile uint32_t tick;
volatile static uint32_t delay;

/*!
    \brief    init systick
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Systick_Init(void)
{
    /* setup systick timer for 1000Hz interrupts */
    if(SysTick_Config(SystemCoreClock / 1000U)) {
        /* capture error */
        while(1) {
        }
    }
}

/*!
    \brief    get the tick
    \param[in]  none
    \param[out] none
    \retval     tick
*/
uint32_t Systick_GetTick(void)
{
    return tick;
}

/*!
    \brief    delay a time in us
    \param[in]  nus: count in us
*/
void Delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD; //LOAD 的值
    ticks = nus * SystemCoreClock / 1000000U; //需要的节拍数
    told = SysTick->VAL; //刚进入时的计数器值
    while(1)
    {
        tnow = SysTick->VAL;
        if(tnow != told)
        {
            //这里注意一下 SYSTICK 是一个递减的计数器就可以了.
            if(tnow < told)
                tcnt += told - tnow;
            else
                tcnt += reload - tnow + told;

            told = tnow;

            if(tcnt >= ticks)break; //时间超过/等于要延迟的时间,则退出.
        }
    }
}

/*!
    \brief    delay a time in milliseconds
    \param[in]  count: count in milliseconds
    \param[out] none
    \retval     none
*/
void Delay_ms(uint32_t count)
{
    delay = count;

    while(0U != delay) {
    }
}

/*!
    \brief    delay decrement
    \param[in]  none
    \param[out] none
    \retval     none
*/
void Delay_Decrement(void)
{
    if(0U != delay) {
        delay--;
    }

    tick++;
}

/*!
    \brief    Calculate the difference between the current tick and the input tick
    \param[in]  none
    \param[out] none
    \retval     The difference between the current tick and the input tick.
*/
uint32_t Systick_GetTickDiff(uint32_t prev_tick)
{
    uint32_t current_tick = Systick_GetTick();
    // 处理溢出问题
    if(current_tick >= prev_tick)
    {
        return current_tick - prev_tick;
    }
    else
    {
        // 发生溢出，计算差值
        return (UINT32_MAX - prev_tick) + current_tick + 1;
    }
}
